﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Cms.Application.Admin.Views;
using Cms.Application.IO;
using Cms.Data;
using Cms.Domain;
using Cms.Domain.Comparers;
using Cms.Domain.RepositoryInterfaces;
using Cms.Utilities;
using iLib.Web.UI;

namespace Cms.Application.Admin.Presenters
{
    public class EditDetailTemplatePresenter : BasePresenter
    {
        private readonly Administrator _administrator;
        private readonly IEditDetailTemplateView _view;

        public IDiskAccess DiskAccess { get; set; }

        public EditDetailTemplatePresenter(IEditDetailTemplateView view)
            : this(view, new RepositoryFactory())
        {
            DiskAccess = new DiskAccess();
        }
        
        public EditDetailTemplatePresenter(IEditDetailTemplateView view, IRepositoryFactory repositoryFactory)
            : base(view, repositoryFactory)
        {
            _view = view;
            _administrator = AdministratorRepository.GetAdministrator(_view.AdministratorID);
            if (!_administrator.HasPermission.EditDetailTemplate)
                _view.RedirectToPermissionDeniedPage();
        }

        public void SetLocales()
        {
            _view.SetLocales(_administrator.CurrentSite.Locales);
        }
        
        public void Initialize()
        {
            if (_administrator.CurrentSiteLocale != null)
            {
                _view.SelectedLocaleID = _administrator.CurrentSiteLocale.ID;
            }
            _view.SetMasterTemplates(_administrator.CurrentSite.MasterTemplates);
            SetVersions();
            if (!_administrator.HasPermission.PublishContent)
            {
                // This check must be done after SetVersions, since that method also affects the possibility to publish
                _view.PublishContentNotAllowed();
            }
            if (_view.DetailTemplateID == -1)
            {
                _view.SourceCode = DiskAccess.ReadTextFile("Admin\\Resources\\NewDetailTemplate.Master");
                if (_administrator.CurrentSite.DefaultMasterTemplate != null)
                {
                    _view.SelectedPreferredMasterTemplateID = _administrator.CurrentSite.DefaultMasterTemplate.ID;
                    _view.SelectedMasterTemplateID = _administrator.CurrentSite.DefaultMasterTemplate.ID;
                }
            }
            else
            {
                DetailTemplate detailTemplate = SiteRepository.GetDetailTemplate(_view.DetailTemplateID);
                _view.Name = detailTemplate.Name;
                _view.Description = detailTemplate.Description;
                _view.SourceCode = detailTemplate.GetCode();
                if (detailTemplate.ContentSets.ContainsKey(_view.SelectedLocaleID))
                {
                    _view.SelectedVersionID = detailTemplate.ContentSets[_view.SelectedLocaleID].TranslationVersions.Last().ID;
                }
                if (detailTemplate.DefaultMasterTemplate != null)
                {
                    _view.SelectedPreferredMasterTemplateID = detailTemplate.DefaultMasterTemplate.ID;
                    _view.SelectedMasterTemplateID = detailTemplate.DefaultMasterTemplate.ID;
                }
                else
                {
                    if (_administrator.CurrentSite.DefaultMasterTemplate != null)
                    {
                        _view.SelectedPreferredMasterTemplateID = _administrator.CurrentSite.DefaultMasterTemplate.ID;
                        _view.SelectedMasterTemplateID = _administrator.CurrentSite.DefaultMasterTemplate.ID;
                    }
                }
            }
        }
        
        public void SetVersions()
        {
            if (_view.DetailTemplateID > 0)
            {
                DetailTemplate detailTemplate = SiteRepository.GetDetailTemplate(_view.DetailTemplateID);
                IList<ContentTranslationVersion> versions = detailTemplate.GetContentVersions(_view.SelectedLocaleID);
                int publishedVersionID = -1;
                if (detailTemplate.ContentSets.ContainsKey(_view.SelectedLocaleID) && detailTemplate.ContentSets[_view.SelectedLocaleID].PublishedVersion != null)
                {
                    publishedVersionID = detailTemplate.ContentSets[_view.SelectedLocaleID].PublishedVersion.ID;
                }
                _view.SetVersions(versions, publishedVersionID);
                List<ScheduledPublishing> scheduledPublishings = versions.SelectMany(ctv => ctv.ScheduledPublishings).ToList();
                scheduledPublishings.Sort(new ScheduledPublishingComparer(SortDirection.Ascending));
                _view.SetScheduledPublishings(scheduledPublishings);
            }
            else
            {
                _view.SetVersions(new List<ContentTranslationVersion>(), -1);
                _view.SetScheduledPublishings(new List<ScheduledPublishing>());
            }
        }
        
        public void Save()
        {
            if (_view.CurrentTab == "properties")
            {
                ValidateProperties();
            }
            if (!IsValid)
            {
                return;
            }
            DetailTemplate detailTemplate;
            if (_view.DetailTemplateID == -1)
            {
                detailTemplate = new DetailTemplate { Site = _administrator.CurrentSite };
                detailTemplate.Site.DetailTemplates.Add(detailTemplate);
                if (_administrator.CurrentSite.DefaultDetailTemplate == null)
                {
                    _administrator.CurrentSite.DefaultDetailTemplate = detailTemplate;
                }
            }
            else
            {
                detailTemplate = SiteRepository.GetDetailTemplate(_view.DetailTemplateID);

                // TODO: Check current Areas and compare them to _view.Areas
            }
            detailTemplate.Name = _view.Name;
            detailTemplate.Description = _view.Description;
            detailTemplate.DefaultMasterTemplate = SiteRepository.GetMasterTemplate(_view.SelectedPreferredMasterTemplateID);
            detailTemplate.SetCode(_view.SourceCode, _administrator);
            string[] areas = _view.DetailTemplateAreas.Split(",".ToCharArray());
            detailTemplate.Areas.Clear();
            foreach (string area in areas.Where(area => area.Trim() != string.Empty))
            {
                detailTemplate.Areas.Add(area);
            }
            string[] pageAreas = _view.PageAreas.Split(",".ToCharArray());
            detailTemplate.PageAreas.Clear();
            foreach (string area in pageAreas.Where(area => area.Trim() != string.Empty))
            {
                detailTemplate.PageAreas.Add(area);
            }
            SiteRepository.SaveSite(_administrator.CurrentSite);
            DiskAccess.DeleteFile("__System\\DetailTemplates\\" + detailTemplate.ID + ".master");
            DiskAccess.CreateTextFile("__System\\DetailTemplates\\" + detailTemplate.ID + ".master", _view.SourceCode);
            _view.SetDetailTemplateID(detailTemplate.ID);
        }
        
        public void SaveSelectedLocale()
        {
            _administrator.CurrentSiteLocale = LocaleRepository.GetLocale(_view.SelectedLocaleID);
            AdministratorRepository.SaveAdministrator(_administrator);
        }
        
        public void Publish()
        {
            DetailTemplate dt = SiteRepository.GetDetailTemplate(_view.DetailTemplateID);
            ContentTranslationVersion ctv = ContentRepository.GetContentTranslationVersion(_view.SelectedVersionID);
            if (ctv == null)
            {
                return;
            }
            ctv.Publish();
            SiteRepository.SaveSite(_administrator.CurrentSite);
            SetVersions();
            _view.SelectedVersionID = ctv.ID;
        }
        
        public IList<ContentSetContainer> GetContentContainers(string areaID, string contentType)
        {
            ContentSetContainer container = null;
            IList<ContentSetContainer> containers = new List<ContentSetContainer>();
            switch (contentType)
            {
                case "MasterTemplateContent":
                    container = SiteRepository.GetMasterTemplate(_view.SelectedMasterTemplateID);
                    break;
                case "DetailTemplateContent":
                    container = SiteRepository.GetDetailTemplate(_view.DetailTemplateID);
                    break;
            }
            if (container == null)
            {
                return containers;
            }
            Content c = container.GetContent(areaID);
            foreach (PageContentLink pl in c.Pages)
            {
                containers.Add(pl.Page);
            }
            foreach (MasterTemplateContentLink mtl in c.MasterTemplates)
            {
                containers.Add(mtl.MasterTemplate);
            }
            foreach (DetailTemplateContentLink dtl in c.DetailTemplates)
            {
                if (dtl.DetailTemplate.ID != _view.DetailTemplateID)
                {
                    containers.Add(dtl.DetailTemplate);
                }
            }
            return containers;
        }
        
        public void BreakContentLink(string areaID, string contentType)
        {
            ContentSetContainer container = null;
            switch (contentType)
            {
                case "MasterTemplateContent":
                    container = SiteRepository.GetMasterTemplate(_view.SelectedMasterTemplateID);
                    break;
                case "DetailTemplateContent":
                    container = SiteRepository.GetDetailTemplate(_view.DetailTemplateID);
                    break;
            }
            if (container == null)
            {
                return;
            }
            Content content = container.GetContent(areaID);
            switch (contentType)
            {
                case "MasterTemplateContent":
                    content.RemoveMasterTemplate((MasterTemplate)container);
                    break;
                case "DetailTemplateContent":
                    content.RemoveDetailTemplate((DetailTemplate)container);
                    break;
            }
            foreach (var translation in content.Translations)
            {
                ContentSet set = container.GetContentSet(LocaleRepository.GetLocale(translation.Key));
                foreach (ContentTranslationVersion ctv in translation.Value.Versions)
                {
                    set.TranslationVersions.Remove(ctv);
                }
            }
            SiteRepository.SaveSite(_administrator.CurrentSite);
            SetVersions();
        }
        
        public void SchedulePublishing(int contentTranslationVersionID, DateTime scheduledPublishingDateTime)
        {
            ContentTranslationVersion ctv = ContentRepository.GetContentTranslationVersion(contentTranslationVersionID);
            if (ctv == null)
            {
                return;
            }
            var scheduledPublishing = new ScheduledPublishing
                                          {
                                              Timestamp = scheduledPublishingDateTime.Ticks.ToString(),
                                              ContentTranslationVersion = ctv,
                                              Description = null
                                          };
            ctv.ScheduledPublishings.Add(scheduledPublishing);
            SiteRepository.SaveSite(_administrator.CurrentSite);
            SetVersions();
        }
        
        public void DeleteScheduledPublishing(int id)
        {
            ContentRepository.DeleteScheduledPublishing(id);
            SetVersions();
        }

        private void ValidateProperties()
        {
            if (_view.Name.Trim() == string.Empty)
            {
                AddValidationError(GetText(_view, "NoNameError"));
            }
            if (!_administrator.CurrentSite.CanDetailTemplateBeNamedTo(_view.DetailTemplateID, _view.Name))
            {
                AddValidationError(GetText(_view, "NameCollisionError"));
            }
            string sourceCodeValidationResult = _view.GetSourceCodeStatus();
            if (sourceCodeValidationResult == "ok")
            {
                return;
            }
            string errorText = GetText(_view, "SourceCodeError");
            errorText = errorText.Replace("[[ErrorMessage]]", sourceCodeValidationResult);
            string encryptedCredentials = Cipher.Encrypt(_administrator.Username + (char)9 + _administrator.Password);
            string url = Url.FullPath + "Admin/Default.aspx?credentials=" +
                         HttpUtility.UrlEncode(encryptedCredentials) + "&ReturnUrl=" +
                         HttpUtility.UrlEncode(_view.UserTempDirectory + "ErrorDetails.aspx?v=" + DateTime.Now.Ticks);
            errorText = errorText.Replace("[[ErrorDetailsUrl]]", url);
            AddValidationError(errorText);
        }
    }
}